import logging
from typing import List, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_
from app.models.role import Role
from app.models.user import User
from app.admin.schemas.role import RoleCreate, RoleUpdate

# 配置日志
logger = logging.getLogger(__name__)


async def get_role(db: AsyncSession, role_id: str, tenant_id: str = None) -> Optional[Role]:
    """
    根据角色ID获取角色
    """
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id == role_id, Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id == role_id))
    return result.scalar_one_or_none()


async def get_role_by_name(db: AsyncSession, name: str, tenant_id: str = None) -> Optional[Role]:
    """
    根据角色名称获取角色
    """
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.name == name, Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.name == name))
    return result.scalar_one_or_none()


async def get_roles(db: AsyncSession, skip: int = 0, limit: int = 100, tenant_id: str = None) -> List[Role]:
    """
    获取角色列表
    """
    if tenant_id:
        result = await db.execute(
            select(Role).where(Role.tenant_id == tenant_id).offset(skip).limit(limit)
        )
    else:
        result = await db.execute(select(Role).offset(skip).limit(limit))
    return result.scalars().all()


async def create_role(db: AsyncSession, role: RoleCreate) -> Role:
    """
    创建新角色
    """
    db_role = Role(
        id=role.id,
        name=role.name,
        description=role.description,
        tenant_id=role.tenant_id,
        created_at=role.created_at,
        updated_at=role.updated_at
    )
    db.add(db_role)
    await db.commit()
    await db.refresh(db_role)
    logger.info(f"角色 [{db_role.id}] 创建成功")
    return db_role


async def update_role(db: AsyncSession, role_id: str, role_update: RoleUpdate) -> Optional[Role]:
    """
    更新角色信息
    """
    db_role = await get_role(db, role_id, role_update.tenant_id)
    if not db_role:
        logger.warning(f"更新角色失败: 角色 [{role_id}] 不存在")
        return None

    update_data = role_update.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_role, key, value)

    await db.commit()
    await db.refresh(db_role)
    logger.info(f"角色 [{role_id}] 更新成功")
    return db_role


async def delete_role(db: AsyncSession, role_id: str, tenant_id: str = None) -> bool:
    """
    删除角色
    """
    db_role = await get_role(db, role_id, tenant_id)
    if not db_role:
        logger.warning(f"删除角色失败: 角色 [{role_id}] 不存在")
        return False

    await db.delete(db_role)
    await db.commit()
    logger.info(f"角色 [{role_id}] 删除成功")
    return True


async def get_user_roles(db: AsyncSession, user_id: str, tenant_id: str = None) -> List[Role]:
    """
    获取用户的角色列表
    """
    if tenant_id:
        result = await db.execute(select(User).where(
            and_(User.id == user_id, User.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(User).where(User.id == user_id))
    
    user = result.scalar_one_or_none()
    if not user:
        logger.warning(f"获取用户角色失败: 用户 [{user_id}] 不存在")
        return []
    
    if tenant_id:
        return [role for role in user.roles if role.tenant_id == tenant_id]
    return user.roles


async def get_role_users(db: AsyncSession, role_id: str, tenant_id: str = None) -> List[User]:
    """
    获取角色的用户列表
    """
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id == role_id, Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id == role_id))
    
    role = result.scalar_one_or_none()
    if not role:
        logger.warning(f"获取角色用户失败: 角色 [{role_id}] 不存在")
        return []
    
    if tenant_id:
        return [user for user in role.users if user.tenant_id == tenant_id]
    return role.users


async def assign_roles_to_user(db: AsyncSession, user_id: str, role_ids: List[str], tenant_id: str = None) -> bool:
    """
    为用户分配角色
    """
    # 获取用户
    if tenant_id:
        result = await db.execute(select(User).where(
            and_(User.id == user_id, User.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(User).where(User.id == user_id))
    
    user = result.scalar_one_or_none()
    if not user:
        logger.warning(f"分配角色失败: 用户 [{user_id}] 不存在")
        return False

    # 获取角色
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id.in_(role_ids), Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id.in_(role_ids)))
    
    roles = result.scalars().all()

    # 分配角色
    user.roles = roles
    await db.commit()
    logger.info(f"用户 [{user_id}] 角色分配成功")
    return True


async def assign_users_to_role(db: AsyncSession, role_id: str, user_ids: List[str], tenant_id: str = None) -> bool:
    """
    为角色分配用户
    """
    # 获取角色
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id == role_id, Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id == role_id))
    
    role = result.scalar_one_or_none()
    if not role:
        logger.warning(f"分配用户失败: 角色 [{role_id}] 不存在")
        return False

    # 获取用户
    if tenant_id:
        result = await db.execute(select(User).where(
            and_(User.id.in_(user_ids), User.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(User).where(User.id.in_(user_ids)))
    
    users = result.scalars().all()

    # 分配用户
    role.users = users
    await db.commit()
    logger.info(f"角色 [{role_id}] 用户分配成功")
    return True


async def remove_user_roles(db: AsyncSession, user_id: str, role_ids: List[str], tenant_id: str = None) -> bool:
    """
    移除用户的角色
    """
    # 获取用户
    if tenant_id:
        result = await db.execute(select(User).where(
            and_(User.id == user_id, User.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(User).where(User.id == user_id))
    
    user = result.scalar_one_or_none()
    if not user:
        logger.warning(f"移除角色失败: 用户 [{user_id}] 不存在")
        return False

    # 获取要移除的角色
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id.in_(role_ids), Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id.in_(role_ids)))
    
    roles_to_remove = result.scalars().all()

    # 移除角色
    for role in roles_to_remove:
        if role in user.roles:
            user.roles.remove(role)

    await db.commit()
    logger.info(f"用户 [{user_id}] 角色移除成功")
    return True


async def check_role_exists(db: AsyncSession, name: str, tenant_id: str = None) -> bool:
    """
    检查角色名称是否存在
    """
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.name == name, Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.name == name))
    
    return result.scalar_one_or_none() is not None


async def get_all_roles(db: AsyncSession, tenant_id: str = None) -> List[Role]:
    """
    获取所有角色
    """
    if tenant_id:
        result = await db.execute(select(Role).where(Role.tenant_id == tenant_id))
    else:
        result = await db.execute(select(Role))
    
    return result.scalars().all()


async def get_roles_by_ids(db: AsyncSession, role_ids: List[str], tenant_id: str = None) -> List[Role]:
    """
    根据角色ID列表获取角色
    """
    if not role_ids:
        return []
    
    if tenant_id:
        result = await db.execute(select(Role).where(
            and_(Role.id.in_(role_ids), Role.tenant_id == tenant_id)
        ))
    else:
        result = await db.execute(select(Role).where(Role.id.in_(role_ids)))
    
    return result.scalars().all()
